package com.bdqn.qnnews.search.service.impl;

import com.alibaba.nacos.api.utils.StringUtils;
import com.bdqn.qnnews.common.base.PageResult;
import com.bdqn.qnnews.common.base.ResultCode;
import com.bdqn.qnnews.rest.exception.ApplicationException;
import com.bdqn.qnnews.search.convert.AppInfoArticleConvert;
import com.bdqn.qnnews.search.entity.AppInfoArticle;
import com.bdqn.qnnews.search.service.ApArticleSearchService;
import com.bdqn.qnnews.search.vo.UserSearchReqVo;
import com.bdqn.qnnews.search.vo.UserSearchRespVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

/**
 * @author xlzhang
 * @date 2024/1/9 11:46
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class ApArticleSearchServiceImpl implements ApArticleSearchService {

    private final ElasticsearchRestTemplate esRestTemplate;

    @Override
    public PageResult<ArrayList<UserSearchRespVo>> search(UserSearchReqVo reqVo) {
        // 判断当前参数是否为空
        if (StringUtils.isEmpty(reqVo.getSearchWords())){
            throw new ApplicationException("查询参数为空");
        }
        // 创建一个bool查询条件对象
        final BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        // 创建一个匹配查询关键字的查询子对象
        boolQueryBuilder.must(QueryBuilders.matchQuery("title", reqVo.getSearchWords()));
        // 创建一个范围查询子对象，基于传入的最小日期
        //将要使用的日期类型格式化为指定的字符串样式
        final String dateStr = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss")
                .format(reqVo.getMinBehotTime());
        boolQueryBuilder.filter(QueryBuilders.rangeQuery("publishTime").lt(dateStr));

        // 创建高亮显示条件对象
        final HighlightBuilder highlightBuilder = new HighlightBuilder()
                .field("title")
                .preTags("<span style='color:red;' >")
                .postTags("</span>");

        // 创建一个查询条件总对象
        final NativeSearchQuery query = new NativeSearchQueryBuilder()
                .withQuery(boolQueryBuilder)
                .withHighlightBuilder(highlightBuilder)
                .withPageable(PageRequest.of(reqVo.getPageNum(), reqVo.getPageSize()))
                .withSort(SortBuilders.fieldSort("publishTime").order(SortOrder.DESC))
                .build();

        // 执行搜索
        final SearchHits<AppInfoArticle> searchHits = esRestTemplate.search(query, AppInfoArticle.class);
        // 创建一个保存响应对象的列表
        final ArrayList<UserSearchRespVo> userSearchRespVoList = new ArrayList<>();
        // 封装返回值对象
        for (SearchHit<AppInfoArticle> searchHit : searchHits) {
            // 将查询到的文章数据转换为响应vo类型
            final UserSearchRespVo userSearchRespVo =
                    AppInfoArticleConvert.INSTANCE.entityToVo(searchHit.getContent());
            // 将高亮数据保存的对象中
            final List<String> highlightField = searchHit.getHighlightField("title");
            final String highlightStr = String.join(",", highlightField);
            userSearchRespVo.setHTitle(highlightStr);
            //userSearchRespVo.setTitle(highlightStr);
            // 保存到列表
            userSearchRespVoList.add(userSearchRespVo);
        }
        log.debug("处理后的响应数据：{}",userSearchRespVoList);
        // 封装分页数据
        final PageResult<ArrayList<UserSearchRespVo>> pageResult =
                PageResult.ok(ResultCode.SUCCESS, userSearchRespVoList);
        pageResult.setTotal((int) searchHits.getTotalHits());
        pageResult.setCurrentPage(reqVo.getPageNum());
        pageResult.setSize(reqVo.getPageSize());

        return pageResult;
    }

    @Override
    public void saveAndUpdateArticle(AppInfoArticle article) {
        esRestTemplate.save(article);
    }

    @Override
    public void deleteArticle(String articleId) {
        esRestTemplate.delete(articleId,AppInfoArticle.class);
    }
}
